package sel.me.popular.library.learning.disruptor.event;

import com.lmax.disruptor.RingBuffer;

import java.nio.ByteBuffer;

/**
 * 使用旧版API发布
 *
 * 显而易见的是，事件发布变得比使用简单队列更复杂。这是由于对事件预分配的需求。
 * 它需要(在最低级别)消息发布的两阶段方法，即声明环形缓冲区中的插槽然后发布可用数据。
 * 还必须将发布包装在try/finally块中。如果我们在Ring Buffer中声明一个插槽(调用RingBuffer.next())
 * ，那么我们必须发布这个序列。如果不这样做可能会导致Disruptor状态的变坏。
 * 具体而言，在多生产者的情况下，这将导致消费者停滞并且在没有重启的情况下无法恢复。
 * 因此，建议使用EventTranslator API。

 *
 * @author shenenlu 2021年05月14日 下午14:34:29
 */
public class LongEventProducer {

    private final RingBuffer<LongEvent> ringBuffer;

    public LongEventProducer(RingBuffer<LongEvent> ringBuffer) {
        this.ringBuffer = ringBuffer;
    }

    public void onData(ByteBuffer bb) {
        long sequence = ringBuffer.next();  // Grab the next sequence
        try {
            LongEvent event = ringBuffer.get(sequence); // Get the entry in the Disruptor
            // for the sequence
            event.set(bb.getLong(0));  // Fill with data
        } finally {
            ringBuffer.publish(sequence);
        }
    }

}
